home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / 92052tar.gz / 920528.tar / ttydriv.c < prev    next >
C/C++ Source or Header  |  1992-03-30  |  10KB  |  478 lines

  1. /* @(#) $Header: ttydriv.c,v 1.12 92/03/30 09:16:51 deyke Exp $ */
  2.  
  3. /* TTY input line editing
  4.  */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8.  
  9. #include "global.h"
  10. #include "tty.h"
  11.  
  12. #define LINESIZE     1024
  13. #define LINEMAX      (LINESIZE-5)
  14. #define RECALLSIZE   63
  15.  
  16. #define NEXT(i)      (((i) + 1) & RECALLSIZE)
  17. #define PREV(i)      (((i) - 1) & RECALLSIZE)
  18.  
  19. char *Fkey_table[NUM_FKEY];
  20. char *Fkey_ptr;
  21.  
  22. static int  ansimode;
  23. static int  rawmode;
  24.  
  25. static void printchr __ARGS((int chr));
  26. static void backchr __ARGS((int chr));
  27. static void delchr __ARGS((int chr));
  28. static void inschr __ARGS((int chr));
  29. static void clreol __ARGS((void));
  30.  
  31. /*---------------------------------------------------------------------------*/
  32.  
  33. int  raw()
  34. {
  35.   rawmode = 1;
  36.   return 0;
  37. }
  38.  
  39. /*---------------------------------------------------------------------------*/
  40.  
  41. int  cooked()
  42. {
  43.   rawmode = 0;
  44.   return 0;
  45. }
  46.  
  47. /*---------------------------------------------------------------------------*/
  48.  
  49. static void printchr(chr)
  50. int  chr;
  51. {
  52.   chr &= 0xff;
  53.   if (chr < 32) {
  54.     putchar('^');
  55.     putchar(chr + 64);
  56.   } else if (chr < 127) {
  57.     putchar(chr);
  58.   } else if (chr < 128) {
  59.     putchar('^');
  60.     putchar('?');
  61.   } else if (chr < 159) {
  62.     putchar('^');
  63.     putchar(chr - 32);
  64.   } else if (chr < 160) {
  65.     putchar('^');
  66.     putchar('>');
  67.   } else if (chr < 255) {
  68.     putchar(chr);
  69.   } else {
  70.     putchar('^');
  71.     putchar('/');
  72.   }
  73. }
  74.  
  75. /*---------------------------------------------------------------------------*/
  76.  
  77. static void backchr(chr)
  78. int  chr;
  79. {
  80.   putchar('\b');
  81.   chr &= 0x7f;
  82.   if (chr < 32 || chr == 127)
  83.     putchar('\b');
  84. }
  85.  
  86. /*---------------------------------------------------------------------------*/
  87.  
  88. static void delchr(chr)
  89. int  chr;
  90. {
  91.   putchar('\033');
  92.   if (ansimode) putchar('[');
  93.   putchar('P');
  94.   chr &= 0x7f;
  95.   if (chr < 32 || chr == 127) {
  96.     putchar('\033');
  97.     if (ansimode) putchar('[');
  98.     putchar('P');
  99.   }
  100. }
  101.  
  102. /*---------------------------------------------------------------------------*/
  103.  
  104. static void inschr(chr)
  105. int  chr;
  106. {
  107.   int  c;
  108.  
  109.   if (ansimode) {
  110.     c = chr & 0x7f;
  111.     printf("\033[%d@", (c < 32 || c == 127) ? 2 : 1);
  112.     printchr(chr);
  113.   } else {
  114.     putchar('\033');
  115.     putchar('Q');
  116.     printchr(chr);
  117.     putchar('\033');
  118.     putchar('R');
  119.   }
  120. }
  121.  
  122. /*---------------------------------------------------------------------------*/
  123.  
  124. static void clreol()
  125. {
  126.   putchar('\033');
  127.   if (ansimode) putchar('[');
  128.   putchar('K');
  129. }
  130.  
  131. /*---------------------------------------------------------------------------*/
  132.  
  133. /* Accept characters from the incoming tty, buffer and process them
  134.  * (if in cooked mode) or just pass them directly (if in raw mode).
  135.  * Returns the number of characters available for use; if non-zero,
  136.  * also stashes a pointer to the character(s) in the "buf" argument.
  137.  */
  138.  
  139. int  ttydriv(chr, buf)
  140. int  chr;
  141. char  **buf;
  142. {
  143.  
  144.   static char  linebuf[LINESIZE];
  145.   static char  *end = linebuf;
  146.   static char  *pos = linebuf;
  147.   static char  *recall_buffer[RECALLSIZE+1];
  148.   static int  Escape_save;
  149.   static int  ansikey;
  150.   static int  esc, quote;
  151.   static int  rptr, wptr;
  152.  
  153.   char  *p, *f, *t;
  154.   int  cnt;
  155.  
  156.   if (rawmode) {
  157.     *linebuf = chr;
  158.     *buf = linebuf;
  159.     return 1;
  160.   }
  161.  
  162.   if (!chr) return 0;
  163.   cnt = 0;
  164.   if (quote) {
  165.     delchr(quote);
  166.     quote = 0;
  167.     Escape = Escape_save;
  168.     if (pos == end) {
  169.       *end++ = chr;
  170.       printchr(*pos++);
  171.     } else {
  172.       for (p = end - 1; p >= pos; p--) p[1] = *p;
  173.       *pos++ = chr;
  174.       end++;
  175.       inschr(chr);
  176.     }
  177.   } else if (ansikey) {
  178.     ansikey = 0;
  179.     switch (chr) {
  180.  
  181.     case 'A': /* up arrow */
  182.       if (recall_buffer[PREV(rptr)]) {
  183.     if (end > linebuf) {
  184.       while (pos > linebuf) backchr(*--pos);
  185.       clreol();
  186.     }
  187.     rptr = PREV(rptr);
  188.     strcpy(linebuf, recall_buffer[rptr]);
  189.     for (pos = linebuf; *pos; pos++) printchr(*pos);
  190.     end = pos;
  191.       } else
  192.     putchar(7);
  193.       break;
  194.  
  195.     case 'B': /* down arrow */
  196.       if (recall_buffer[rptr] && recall_buffer[NEXT(rptr)]) {
  197.     if (end > linebuf) {
  198.       while (pos > linebuf) backchr(*--pos);
  199.       clreol();
  200.     }
  201.     rptr = NEXT(rptr);
  202.     strcpy(linebuf, recall_buffer[rptr]);
  203.     for (pos = linebuf; *pos; pos++) printchr(*pos);
  204.     end = pos;
  205.       } else
  206.     putchar(7);
  207.       break;
  208.  
  209.     case 'C': /* cursor right */
  210.       if (pos - linebuf >= LINEMAX)
  211.     putchar(7);
  212.       else {
  213.     if (pos == end) *end++ = ' ';
  214.     printchr(*pos++);
  215.       }
  216.       break;
  217.  
  218.     case 'D': /* cursor left */
  219.       if (pos > linebuf) backchr(*--pos);
  220.       break;
  221.  
  222.     case 'P': /* ansi function key 1 */
  223.       Fkey_ptr = Fkey_table[0];
  224.       break;
  225.  
  226.     case 'Q': /* ansi function key 2 */
  227.       Fkey_ptr = Fkey_table[1];
  228.       break;
  229.  
  230.     case 'R': /* ansi function key 3 */
  231.       Fkey_ptr = Fkey_table[2];
  232.       break;
  233.  
  234.     case 'S': /* ansi function key 4 */
  235.       Fkey_ptr = Fkey_table[3];
  236.       break;
  237.  
  238.     case 'T': /* ansi function key 5 */
  239.     case 'w': /* ansi function key 5 */
  240.       Fkey_ptr = Fkey_table[4];
  241.       break;
  242.  
  243.     case 'U': /* ansi function key 6 */
  244.     case 'x': /* ansi function key 6 */
  245.       Fkey_ptr = Fkey_table[5];
  246.       break;
  247.  
  248.     case 'V': /* ansi function key 7 */
  249.     case 'y': /* ansi function key 7 */
  250.       Fkey_ptr = Fkey_table[6];
  251.       break;
  252.  
  253.     case 'W': /* ansi function key 8 */
  254.     case 'm': /* ansi function key 8 */
  255.       Fkey_ptr = Fkey_table[7];
  256.       break;
  257.  
  258.     case 'X': /* ansi function key 9 */
  259.     case 't': /* ansi function key 9 */
  260.       Fkey_ptr = Fkey_table[8];
  261.       break;
  262.  
  263.     case 'Y': /* ansi function key 10 */
  264.     case 'u': /* ansi function key 10 */
  265.       Fkey_ptr = Fkey_table[9];
  266.       break;
  267.  
  268.     }
  269.   } else if (!esc) {
  270.     switch (chr) {
  271.  
  272.     case '\b': /* backspace */
  273.       if (pos > linebuf) {
  274.     backchr(*--pos);
  275.     delchr(*pos);
  276.     for (p = pos + 1; p < end; p++) p[-1] = *p;
  277.     end--;
  278.       }
  279.       break;
  280.  
  281.     case '\n': /* linefeed */
  282.     case '\r': /* return */
  283.     case 20:   /* control T, transmit line */
  284.       *end = '\0';
  285.       if (*linebuf && strcmp(linebuf, recall_buffer[PREV(wptr)])) {
  286.     recall_buffer[wptr] = strcpy(malloc(end - linebuf + 1), linebuf);
  287.     wptr = NEXT(wptr);
  288.     if (recall_buffer[wptr]) {
  289.       free(recall_buffer[wptr]);
  290.       recall_buffer[wptr] = 0;
  291.     }
  292.       }
  293.       rptr = wptr;
  294.       if (chr != 20) {
  295.     *end++ = '\r';
  296.     *end++ = '\n';
  297.     *end   = '\0';
  298.     putchar('\n');
  299.       }
  300.       cnt = end - linebuf;
  301.       pos = end = linebuf;
  302.       break;
  303.  
  304.     case 18: /* control R, redisplay line */
  305.       putchar('\n');
  306.       for (p = linebuf; p < end; p++) printchr(*p);
  307.       while (p > pos) backchr(*--p);
  308.       break;
  309.  
  310.     case 21: /* control U, delete line */
  311.     case 24: /* control X, delete line */
  312.       if (end > linebuf) {
  313.     while (pos > linebuf) backchr(*--pos);
  314.     end = linebuf;
  315.     clreol();
  316.       }
  317.       break;
  318.  
  319.     case 22: /* control V, quote next character */
  320.       if (end - linebuf >= LINEMAX)
  321.     putchar(7);
  322.       else {
  323.     Escape_save = Escape;
  324.     Escape = 0;
  325.     quote = '^';
  326.     if (pos == end)
  327.       printchr(quote);
  328.     else
  329.       inschr(quote);
  330.     backchr(quote);
  331.       }
  332.       break;
  333.  
  334.     case 23: /* control W, delete word */
  335.       p = pos;
  336.       while (p > linebuf && p[-1] == ' ') { backchr(*--p); delchr(*p); }
  337.       while (p > linebuf && p[-1] != ' ') { backchr(*--p); delchr(*p); }
  338.       for (f = pos, t = p; f < end; ) *t++ = *f++;
  339.       pos = p;
  340.       end = t;
  341.       break;
  342.  
  343.     case 27: /* escape */
  344.       esc = 1;
  345.       ansimode = 0;
  346.       break;
  347.  
  348.     case 127: /* DEL, delete char */
  349.       if (pos < end) {
  350.     delchr(*pos);
  351.     for (p = pos + 1; p < end; p++) p[-1] = *p;
  352.     end--;
  353.       }
  354.       break;
  355.  
  356.     default:
  357.       if (end - linebuf >= LINEMAX)
  358.     putchar(7);
  359.       else if (pos == end) {
  360.     *end++ = chr;
  361.     printchr(*pos++);
  362.       } else {
  363.     for (p = end - 1; p >= pos; p--) p[1] = *p;
  364.     *pos++ = chr;
  365.     end++;
  366.     inschr(chr);
  367.       }
  368.       break;
  369.  
  370.     }
  371.   } else {
  372.     esc = 0;
  373.     switch (chr) {
  374.  
  375.     case 'A': /* up arrow */
  376.     case 'V': /* prev page */
  377.       if (recall_buffer[PREV(rptr)]) {
  378.     if (end > linebuf) {
  379.       while (pos > linebuf) backchr(*--pos);
  380.       clreol();
  381.     }
  382.     rptr = PREV(rptr);
  383.     strcpy(linebuf, recall_buffer[rptr]);
  384.     for (pos = linebuf; *pos; pos++) printchr(*pos);
  385.     end = pos;
  386.       } else
  387.     putchar(7);
  388.       break;
  389.  
  390.     case 'B': /* down arrow */
  391.     case 'U': /* next page */
  392.       if (recall_buffer[rptr] && recall_buffer[NEXT(rptr)]) {
  393.     if (end > linebuf) {
  394.       while (pos > linebuf) backchr(*--pos);
  395.       clreol();
  396.     }
  397.     rptr = NEXT(rptr);
  398.     strcpy(linebuf, recall_buffer[rptr]);
  399.     for (pos = linebuf; *pos; pos++) printchr(*pos);
  400.     end = pos;
  401.       } else
  402.     putchar(7);
  403.       break;
  404.  
  405.     case 'C': /* cursor right */
  406.       if (pos - linebuf >= LINEMAX)
  407.     putchar(7);
  408.       else {
  409.     if (pos == end) *end++ = ' ';
  410.     printchr(*pos++);
  411.       }
  412.       break;
  413.  
  414.     case 'D': /* cursor left */
  415.       if (pos > linebuf) backchr(*--pos);
  416.       break;
  417.  
  418.     case 'F': /* cursor home down */
  419.     case 'Y': /* end */
  420.       while (pos < end) printchr(*pos++);
  421.       break;
  422.  
  423.     case 'H': /* cursor home up */
  424.     case 'h': /* cursor home up */
  425.       while (pos > linebuf) backchr(*--pos);
  426.       break;
  427.  
  428.     case 'J': /* clear display */
  429.     case 'M': /* delete line */
  430.       while (pos > linebuf) backchr(*--pos);
  431.     case 'K': /* clear line */
  432.       if (end > pos) {
  433.     end = pos;
  434.     clreol();
  435.       }
  436.       break;
  437.  
  438.     case 'O': /* ansi arrow or function key */
  439.       ansimode = ansikey = 1;
  440.       break;
  441.  
  442.     case 'P': /* delete char */
  443.       if (pos < end) {
  444.     delchr(*pos);
  445.     for (p = pos + 1; p < end; p++) p[-1] = *p;
  446.     end--;
  447.       }
  448.       break;
  449.  
  450.     case '[': /* ansi escape sequence */
  451.       esc = ansimode = 1;
  452.       break;
  453.  
  454.     case 'p': /* hp function key 1 */
  455.     case 'q': /* hp function key 2 */
  456.     case 'r': /* hp function key 3 */
  457.     case 's': /* hp function key 4 */
  458.     case 't': /* hp function key 5 */
  459.     case 'u': /* hp function key 6 */
  460.     case 'v': /* hp function key 7 */
  461.     case 'w': /* hp function key 8 */
  462.       Fkey_ptr = Fkey_table[chr - 'p'];
  463.       break;
  464.  
  465.     default:
  466.       putchar('\033');
  467.       if (ansimode) putchar('[');
  468.       putchar(chr);
  469.       break;
  470.  
  471.     }
  472.   }
  473.   fflush(stdout);
  474.   if (cnt) *buf = linebuf;
  475.   return cnt;
  476. }
  477.  
  478.